package drds.plus.executor.command_handler.put;

import drds.plus.executor.ExecuteContext;
import drds.plus.executor.ExecutorException;
import drds.plus.executor.cursor.cursor.ISortingCursor;
import drds.plus.executor.data_node_executor.DataNodeExecutorContext;
import drds.plus.executor.function.scalar.ScalarFunction;
import drds.plus.executor.record_codec.RecordCodecFactory;
import drds.plus.executor.record_codec.record.Record;
import drds.plus.executor.row_values.RowValues;
import drds.plus.executor.table.ITable;
import drds.plus.executor.utils.Utils;
import drds.plus.sql_process.abstract_syntax_tree.configuration.ColumnMetaData;
import drds.plus.sql_process.abstract_syntax_tree.configuration.IndexMapping;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.dml.IPut;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Function;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.FunctionType;

import java.util.ArrayList;
import java.util.List;

public class UpdateHandler extends PutHandler {

    public UpdateHandler() {
        super();
    }

    protected int executePut(ExecuteContext executeContext, IPut put, ITable table, IndexMapping indexMapping) throws RuntimeException {
        int affectRows = 0;
        IPut iPut = put;
        ISortingCursor cursor = null;
        try {
            cursor = DataNodeExecutorContext.getExecutorContext().getDataNodeExecutor().execute(executeContext, iPut.getQuery());//条件
            IndexMapping primaryKeyIndexMapping = table.getTableMetaData().getPrimaryKeyIndexMetaData();
            Record keyRecord = RecordCodecFactory.newRecordCodec(primaryKeyIndexMapping.getKeyColumnMetaDataList()).newRecord();
            Record valueRecord = RecordCodecFactory.newRecordCodec(primaryKeyIndexMapping.getValueColumnMetaDataList()).newRecord();
            RowValues rowData = null;
            while ((rowData = cursor.next()) != null) {
                affectRows++;
                for (ColumnMetaData columnMetaData : primaryKeyIndexMapping.getValueColumnMetaDataList()) {
                    Object value = getValue(rowData, columnMetaData);//查询出来的数据
                    valueRecord.put(columnMetaData.getColumnName(), value);
                    for (int i = 0; i < iPut.getUpdateItemList().size(); i++) {
                        String columnName = Utils.getColumn(iPut.getUpdateItemList().get(i)).getColumnName();
                        if (columnMetaData.getColumnName().equals(columnName)) {
                            Object object = iPut.getUpdateValues().get(i);
                            if (object != null) {
                                if (object instanceof Function) {
                                    if (((Function) object).getFunctionType().equals(FunctionType.aggregate_function)) {
                                        throw new ExecutorException("update is not support aggregate_function function");
                                    }
                                    Function function = ((Function) object);
                                    object = ((ScalarFunction) function.getExtraFunction()).scalarCalucate(executeContext, null);
                                }
                            }
                            valueRecord.put(columnName, object);//更新值
                        }
                    }
                }
                for (ColumnMetaData columnMetaData : primaryKeyIndexMapping.getKeyColumnMetaDataList()) {
                    Object value = getValue(rowData, columnMetaData);//查询出来的数据
                    keyRecord.put(columnMetaData.getColumnName(), value);
                    for (int i = 0; i < iPut.getUpdateItemList().size(); i++) {
                        String columnName = (Utils.getColumn(iPut.getUpdateItemList().get(i))).getColumnName();
                        Object object = iPut.getUpdateValues().get(i);
                        if (columnMetaData.getColumnName().equals(columnName)) {
                            keyRecord.put(columnName, object);//更新值
                        }
                    }
                }
                table.put(executeContext, put.getTableName(), indexMapping, keyRecord, valueRecord);
            }
        } catch (RuntimeException ex) {
            throw ex;
        } finally {
            if (cursor != null) {
                List<RuntimeException> exs = new ArrayList();
                exs = cursor.close(exs);
                if (!exs.isEmpty()) {
                    throw exs.get(0);
                }
            }
        }
        return affectRows;
    }

    private Object getValue(RowValues rowData, ColumnMetaData columnMetaData) {
        Object value = Utils.getValue(rowData, columnMetaData.getTableName(), columnMetaData.getColumnName(), columnMetaData.getAlias());
        return value;
    }

}
